/*
 * Copyright 2002-2016 the Beijing Brain Technology co.,LTD http://www.bris.cn/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bris.niosocket.handler.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bris.niosocket.message.Codecable;
import com.bris.niosocket.message.custom.CmbcSeriaNumber;
import com.bris.niosocket.message.impl.RequestMessage;
import com.bris.niosocket.message.util.CodeUtil;

/**
 * TODO 描述该类型的作用</br>
 * 2016年2月15日</br>
 * @author xunaidong
 * @since 1.0.0
 */
public class RequestDecoder extends ByteToMessageDecoder implements Codecable{
	
	private static final Logger log = LoggerFactory.getLogger(RequestDecoder.class);

	/* (non-Javadoc)
	 * @see io.netty.handler.codec.ByteToMessageDecoder#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf, java.util.List)
	 */
	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf buf,List<Object> out) throws Exception {
		 // 设置为系统字节大小端,以提高效率
        buf = buf.order(ByteOrder.nativeOrder());
        if (buf.readableBytes() < PACKET_LENGTH_FIELD_LEN) {
        	log.debug("可读字节:{}",buf.readableBytes());
            return;
        }
        byte[] lengthDate = new byte[4];
        buf.readBytes(lengthDate);
        int length = CodeUtil.bytes4ToInt(lengthDate);//获取请求报文长度
        log.debug("message length is {}",length);
        if(length<1||length>20480){
        	log.error("无效的请求数据,请求数据长度为{}",length);
        	return;
        }
        log.debug("netty buf is {}",buf);
        if(length-PACKET_LENGTH_FIELD_LEN!=buf.readableBytes()){
        	buf.resetReaderIndex();//
        	return;
        }
        ByteBuffer buffer =  ByteBuffer.allocate(buf.readableBytes());
        byte[] data = new byte[buf.readableBytes()];
        buf.readBytes(data);
        buffer.put(data).flip();
        log.debug("message buffer is {}",buffer);
        RequestMessage message = new RequestMessage();
       	byte[] msgByte = buffer.array();
		int position = buffer.position();//should 0
		int limit = buffer.limit();
		int commondId = CodeUtil.bytes4ToInt(msgByte, position);// 获取命令值,4个字节
		position += 4;
		log.debug("命令代码:{}",commondId);
		try {
			String seriaNumber = new String(msgByte, position, 32,"utf-8");
			message.setSerialNumber(new CmbcSeriaNumber(seriaNumber));
			log.debug("流水号:{}",seriaNumber);
		} catch (UnsupportedEncodingException e) {
		}
		position += 32 + 1 + 4 + 2;// 跳过 verion、prefix与statue
		int kvNumber = CodeUtil.bytes2UnsignShort(msgByte, position);
		log.debug("响应数据键值对数量为:{}",kvNumber);
		position += 2;
		for(;position<limit;){
			int keyLen = CodeUtil.bytes2UnsignShort(msgByte, position);
			position += 2;
			try {
	            String name = new String(msgByte, position, keyLen, "utf-8");
	            log.debug("取KEY值:{}",name);
	            position += keyLen;
	            int valueLen = CodeUtil.bytes4ToInt(msgByte, position);
	            position += 4;
	            buffer.position(position);//同步读指针
	            int valuesize = buffer.getInt();
	            position = buffer.position();
	            String[] values = new String[valuesize];
	            for(int i = valuesize;i>0;i--){
	            	int valueSize = CodeUtil.bytes4ToInt(msgByte, position);//获取单个值长度
	            	position +=4;
	            	values[valuesize-i] = new String(msgByte,position,valueSize,"utf-8");
	            	position += valueSize; 
	            	log.debug(name+"键对应的第{}个值为:"+values[valuesize-i]+",共{}个值",valuesize-i,valuesize);
	            }
	            message.push(name, values);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		out.add(message);

	}

	/* (non-Javadoc)
	 * @see com.bris.niosocket.handler.message.Codecable#getEncoding()
	 */
	@Override
	public String getEncoding() {
		// TODO Auto-generated method stub
		return "UTF-8";
	}

}
